﻿using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace BlazorProject.Common.Helper
{
    public class EncryptionHelper
    {
        /// <summary>
        /// SHA1
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static string SHA1(string text)
        {
            byte[] cleanBytes = Encoding.UTF8.GetBytes(text);
            byte[] hashedBytes = System.Security.Cryptography.SHA1.Create().ComputeHash(cleanBytes);
            return BitConverter.ToString(hashedBytes).Replace("-", "");
        }

        /// <summary>
        /// MD5 通用 16位 小写
        /// </summary>
        /// <param name="origin"></param>
        /// <returns></returns>
        public static string MD5(string origin)
        {
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            string output = BitConverter.ToString(md5.ComputeHash(Encoding.UTF8.GetBytes(origin)), 4, 8);
            return output.Replace("-", "");
        }

        /// <summary>
        /// MD5 加密 32位
        /// </summary>
        /// <param name="srcString"></param>
        /// <returns></returns>
        public static string MD5(string srcString, Encoding encoding)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] t = md5.ComputeHash(encoding.GetBytes(srcString));
            StringBuilder sb = new StringBuilder(32);
            for (int i = 0; i < t.Length; i++)
            {
                sb.Append(t[i].ToString("x").PadLeft(2, '0'));
            }
            return sb.ToString();
        }
        /// <summary>
        /// 32位MD5加密方法，对应Java：DigestUtils.md5Hex
        /// </summary>
        /// <param name="signStr">待加密串</param>
        /// <returns></returns>
        public static string Md5(string signStr)
        {
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            byte[] dataHash = md5.ComputeHash(Encoding.UTF8.GetBytes(signStr));
            StringBuilder sb = new StringBuilder();
            foreach (byte b in dataHash)
            {
                sb.Append(b.ToString("x2").ToLower());
            }
            return sb.ToString();
        }

        /// <summary>
        /// 32位MD5加密方法，对应Java：DigestUtils.md5Hex
        /// </summary>
        /// <param name="signStr">待加密串</param>
        /// <param name="encoding">编码方式</param>
        /// <returns></returns>
        public static string Md5(string signStr, Encoding encoding)
        {
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            byte[] dataHash = md5.ComputeHash(encoding.GetBytes(signStr));
            StringBuilder sb = new StringBuilder();
            foreach (byte b in dataHash)
            {
                sb.Append(b.ToString("x2").ToLower());
            }
            return sb.ToString();
        }
        /// <summary>
        /// RSA
        /// </summary>
        /// <param name="origin"></param>
        /// <returns></returns>
        public static string RSA(string origin)
        {
            byte[] result = Encoding.UTF8.GetBytes(origin);
            RSA rsa = new RSACryptoServiceProvider();
            byte[] output = rsa.EncryptValue(result);
            return BitConverter.ToString(output).Replace("-", "").ToLower();
        }

        #region DES
        protected static byte[] MakeMD5(byte[] a)
        {
            using (MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider())
            {
                return hashmd5.ComputeHash(a);
            }
        }
        public enum CType
        {
            encrypt,
            decrypt
        }
        public static string DES(CType t, string s, string k, string encoding = "UTF-8")
        {
            Encoding e = Encoding.GetEncoding(encoding);
            if (t == CType.encrypt)
                return Convert.ToBase64String(DES(t, e.GetBytes(s), e.GetBytes(k)));
            else
                return e.GetString(DES(t, Convert.FromBase64String(s), e.GetBytes(k)));
        }
        public static byte[] DES(CType t, byte[] s, byte[] k)
        {
            DESCryptoServiceProvider csp = new DESCryptoServiceProvider();
            MemoryStream ms = new MemoryStream();
            //custom
            k = MakeMD5(k);
            int n = k[0] % k.Length;
            int m = k[k.Length - 1] % k.Length;

            k = k.Concat(k).ToArray();

            csp.Key = k.Skip(n).Take(8).ToArray();
            csp.IV = k.Skip(n + 8).Take(8).ToArray();
            CryptoStream cs = new CryptoStream(ms, t == CType.encrypt ? csp.CreateEncryptor() : csp.CreateDecryptor(), CryptoStreamMode.Write);
            cs.Write(s, 0, s.Length);
            cs.FlushFinalBlock();
            if (ms != null)
            {
                ms.Close();
            }
            if (cs != null)
            {
                cs.Close();
            }
            return ms.ToArray();
        }
        /// <summary>
        /// TripleDES
        /// </summary>
        /// <param name="t"></param>
        /// <param name="s"></param>
        /// <param name="k"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static string TDES(CType t, string s, string k, string encoding = "UTF-8")
        {
            Encoding e = Encoding.GetEncoding(encoding);
            if (t == CType.encrypt)
                return Convert.ToBase64String(TDES(t, e.GetBytes(s), e.GetBytes(k)));
            else
                return e.GetString(TDES(t, Convert.FromBase64String(s), e.GetBytes(k)));
        }
        public static byte[] TDES(CType t, byte[] s, byte[] k)
        {
            TripleDESCryptoServiceProvider tdesc = new TripleDESCryptoServiceProvider();
            tdesc.Mode = CipherMode.ECB;
            tdesc.Key = MakeMD5(k);
            if (t == CType.encrypt)
                return tdesc.CreateEncryptor().TransformFinalBlock(s, 0, s.Length);
            else
                return tdesc.CreateDecryptor().TransformFinalBlock(s, 0, s.Length);
        }
        #endregion
    }
}
